﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Presentation.Shell.Interfaces;
using System.ComponentModel;
using Microsoft.Practices.Prism.Commands;
using Presentation.Module.Security.Model;
using System.Windows.Input;
using Application.Interfaces;
using Microsoft.Practices.Unity;
using System.Windows;
using Presentation.Module.Security.Interfaces.Services;
using Infrastructure.CrossCutting.Security;
using System.Web.Security;

namespace VPL.Shell
{
    public class LogonService : ILogonService, INotifyPropertyChanged
    {
        private LoginAttempt _currentAttempt;
        private IUnityContainer _container;
        private readonly IUserService _userService;

        public LogonService(IUnityContainer container)
        {
            _container = container;
            _userService = _container.Resolve<IUserService>();
            _currentAttempt = new LoginAttempt();
            this.Authenticate = new DelegateCommand(this.OnAuthenticate);

            //The creation of the following Administrator User is purely for testing of the prototype for outside parties
            //This must be taken out if prototype is developed into full scale solution
            var tempAdmin = _userService.FindUser("Administrator");
            if(tempAdmin == null)
            {
                var tempRole = new Role() { Name = "Administrator" };
                tempRole.Permissions.UserManagementPermission.CanRead = true;
                tempRole.Permissions.UserManagementPermission.CanWrite = true;
                tempRole.Permissions.SetupPermission.CanRead = true;
                tempRole.Permissions.SetupPermission.CanWrite = true;
                tempRole.Permissions.StudyDefinitionPermission.CanRead = true;
                tempRole.Permissions.StudyDefinitionPermission.CanWrite = true;
                tempRole.Permissions.SchedulingPermission.CanRead = true;
                tempRole.Permissions.SchedulingPermission.CanWrite = true;
                tempRole.Permissions.ReportingPermission.CanRead = true;
                tempRole.Permissions.ReportingPermission.CanWrite = true;

                var tempUser = new User() { UserName = "Administrator", UserRole = tempRole };
                tempUser.ChangePassword("password1");

                _userService.AddUser(tempUser);
            }
            
        }

        public LoginAttempt CurrentAttempt
        {
            get
            {
                return this._currentAttempt;
            }

            set
            {
                if (value == null)
                {
                    return;
                }

                this._currentAttempt = value;
                this.RaiseOnPropertyChanged("CurrentAttempt");
            }
        }

        public ICommand Authenticate { get; private set; }

        public void OnAuthenticate()
        {
            if (LogonTry != null)
            {
                LogonTry.Invoke();
            }

            var user = _userService.FindUser(_currentAttempt.UserName);

            if( user == null)
            {
                MessageBox.Show(
                    "The username or password you have entered is incorrect, please try again", "Logon Error",
                    MessageBoxButton.OK);
                return;
            }

            Password = HashPassword(Password);
            
            if (AuthenticateUser(user, Password))
            {
                CurrentUser.RegisterUser(user);
                UserIsAuthenticated();
            }
            else
            {
                MessageBox.Show(
                    "The username or password you have entered is incorrect, please try again", "Logon Error",
                    MessageBoxButton.OK);
            }               
        }

        public bool AuthenticateUser(User user, string password)
        {
            if (user.UserPassword.HashedPassword != password)
            {
                return false;
                
            }                
            else
            {
                return true;
            }
        }

        private void UserIsAuthenticated()
        {
            if (this.UserAuthenticated != null)
            {
                this.UserAuthenticated.Invoke();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public event Authenticated UserAuthenticated;

        protected void RaiseOnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }

        }

        public event ButtonPressed LogonTry;

        public string Password { get; set; }


        public string HashPassword(string password)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(password, "sha1");
        }
    }
}
